package com.hoas.api.config;

import com.hoas.api.core.entity.BusinessUser;
import com.hoas.api.core.entity.UserToken;
import com.hoas.api.core.entity.api.BusinessApi;
import com.hoas.api.core.intf.ApiListener;
import com.hoas.api.core.intf.BusinessApiConfig;
import com.hoas.api.core.intf.TokenStorage;
import com.hoas.api.encrypt.type.MD5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

public class DBApiConfig implements BusinessApiConfig {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    /**
     * 接口调用前监听器
     */
    private List<ApiListener> apiListeners = new ArrayList<>();

    private TokenStorage tokenStorage;
    /**
     * TOKEN保持时长（分）
     */
    private long tokenKeepTime = 120;

    @Override
    public void initConfigs() throws Exception {

    }

    @Override
    public BusinessApi getApi(String businessId) {

        try {
            RowMapper<BusinessApi > rm = new BeanPropertyRowMapper<BusinessApi>(BusinessApi.class);
            return getJdbcTemplate().queryForObject("SELECT t.api_id, t.business_id, t.type, t.description FROM business_api t WHERE t.business_id = '" + businessId + "'", rm);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    @Override
    public boolean isAuthorized(BusinessUser user, BusinessApi api) {

        int count = getJdbcTemplate().queryForObject("SELECT count(1) FROM api_user_auths t WHERE t.user_id = " +user.getPrimaryKey() + " AND t.api_id = " + api.getApiId(), Integer.class);

        return count > 0;
    }

    @Override
    public BusinessUser getUserByUsername(String username) {

        try {
            RowMapper<BusinessUser > rm = new BeanPropertyRowMapper<BusinessUser>(BusinessUser.class);
            return getJdbcTemplate()
                    .queryForObject("SELECT t.user_id primaryKey, t.user_name, t.`password`, t.encrypt_type, t.create_time FROM api_user t WHERE t.user_name = '" + username +"'", rm);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }

    }

    @Override
    public UserToken getToken(BusinessUser user) {
        // 可以从缓存取，不走数据库

        UserToken token = null;
        if (user.isNeedLogin()) {

            String salt = user.getPrimaryKey() + new Date().getTime();
            String accessToken = MD5.sign(salt, UUID.randomUUID().toString(), "UTF-8");
            String refreshToken = MD5.sign(salt, UUID.randomUUID().toString(), "UTF-8");
            token = new UserToken(user.getPrimaryKey(), accessToken, refreshToken);
            token.setExpireTime(new Date().getTime() + tokenKeepTime * 6000);

            // 设置刷新token 跟 token 之间的缓存映射
            // 设置权限token 跟 token 之间的映射
            tokenStorage.storageToken(token,tokenKeepTime);
            //userRefreshTokenCache.put(refreshToken, accessToken);
            //userRefreshTokenAndAccessTokenRel.put(accessToken, refreshToken);


        } else {
            token = new UserToken(user.getPrimaryKey(), user.getPrimaryKey(), null);
            token.setExpireTime(0);
        }

        // 缓存中增加 权限token 的 真实 token持久化数据
        //userTokenCache.put(accessToken, token);

        return token;
    }

    @Override
    public UserToken refreshToken(String refreshToken) {
        // 刷新缓存
        String accessToken = tokenStorage.getAccessToken(refreshToken);
        if (accessToken == null || "".equals(accessToken)) {
            return null;
        }

        BusinessUser user = getUserByAccessToken(accessToken);
        if (user == null) {
            return null;
        }

        return getToken(user);


    }

    @Override
    public BusinessUser getUserByAccessToken(String accessToken) {


        UserToken userToken = tokenStorage.getUserToken(accessToken);
        if (userToken == null) {
            return null;
        }

        if (userToken.getExpireTime() == 0 || userToken.getExpireTime() >= new Date().getTime()) {

            try {
                RowMapper<BusinessUser > rm = new BeanPropertyRowMapper<BusinessUser>(BusinessUser.class);
                return getJdbcTemplate()
                        .queryForObject("SELECT t.user_id primaryKey, t.user_name, t.`password`, t.encrypt_type, t.create_time FROM api_user t WHERE t.user_id = '" + userToken.getUser() +"'", rm);
            } catch (EmptyResultDataAccessException e) {
            }

        }

        tokenStorage.removeStorage(accessToken);

        return null;
    }




    public void setTokenKeepTime(long tokenKeepTime) {
        this.tokenKeepTime = tokenKeepTime;
    }

    public long getTokenKeepTime() {
        return tokenKeepTime;
    }

    public TokenStorage getTokenStorage() {
        return tokenStorage;
    }

    public void setTokenStorage(TokenStorage tokenStorage) {
        this.tokenStorage = tokenStorage;
    }

    @Override
    public List<ApiListener> getApiListeners() {
        return apiListeners;
    }

    public void setApiListeners(List<ApiListener> apiListeners) {
        this.apiListeners = apiListeners;
    }

}
